#include "StepByStep.h"

Bool EqualTwoTokenLists(TokenList *Pd1, TokenList *Pd2)
{
  if (Pd1->VList.ParaIdx != Pd2->VList.ParaIdx) return FALSE;

  Pd1 = Pd1->next;
  Pd2 = Pd2->next;
  while (Pd1 != NULL) {
    if (!EqualTwoVLists(&(Pd1->VList), &(Pd2->VList))) break;
    Pd1 = Pd1->next;
    Pd2 = Pd2->next;
  }

  return (Pd1==NULL);
}

Bool CheckTheFact(PredKnowledge *Pd)
{
  TypedList *Pt1;
  TokenList *Pt2;
  PredFact  *Ft;
  Bool      Ok;

  for (Ft = State[Pd->PredNo].List; Ft != NULL; Ft = Ft->next) {
    Pt1 = Pd->Para;
    for (Pt2 = Ft->Para; Pt2 != NULL; Pt1++,Pt2=Pt2->next)
      if (!CheckValueList(Pt2->VList.List->Idx, &(Pt1->VList))) break;

    if (Pt2 == NULL) break;
  }

  Ok = (Ft != NULL);
  if (Pd->Type == NOT) Ok = !Ok;

  return Ok;
}

Bool CheckTheFactWithLeftFact(PredKnowledge *Pd)
{
  TypedList *Pt1;
  TokenList *Pt2;
  PredFact  *Ft;
  Bool      Ok;
  int       Num;

  Num = (State[Pd->PredNo].Left==0 ? 1 : State[Pd->PredNo].Total);
  for (Ft = State[Pd->PredNo].List; Num>0 && Ft!=NULL; Num--,Ft=Ft->next) {
    Pt1 = Pd->Para;
    for (Pt2 = Ft->Para; Pt2 != NULL; Pt1++,Pt2=Pt2->next)
      if (!CheckValueList(Pt2->VList.List->Idx, &(Pt1->VList))) break;

    if (Pt2 == NULL) break;
  }

  Ok = (Num > 0);
  if (Pd->Type == NOT) Ok = !Ok;

  return Ok;
}

int FindAndInstantByFacts(PredKnowledge *Pred)
{
  TypedList *P1, *Para;
  TokenList *Pt2, *Pt3;
  PredFact  *Fact;
  int       Num, PNo, SAT;

  PNo = Pred->PredNo;
  if (State[PNo].Left == 0) return 0;

  Num = NumParaOfPred(PNo);
  Para = P1 = (TypedList *) calloc(Num, sizeof(TypedList));

  SAT = 0;
  for (Fact = State[PNo].List; Fact != NULL; Fact = Fact->next) {
    P1 = Pred->Para;
    for (Pt2 = Fact->Para; Pt2 != NULL; P1++,Pt2=Pt2->next)
      if (!CheckValueList(Pt2->VList.List->Idx, &(P1->VList))) break;

    if (Pt2 == NULL) {
       P1 = Para;
       for (Pt3 = Fact->Para; Pt3 != NULL; P1++,Pt3=Pt3->next)
         MergeTwoVLists(&(P1->VList), &(Pt3->VList));

       SAT++;
    }
  }

  if (SAT > 0) ChangeParaOfPredByTypedList(Pred, Para);

  FreeTypedArray(Num, Para);

  return SAT;
}

Bool IsTarget(TokenList *Effect)
{
  TokenList *Pt1, *Pt2;
  PredFact  *FT;

  for (FT = State[Effect->VList.ParaIdx].List; FT != NULL; FT = FT->next) {
    Pt1 = Effect->next;
    for (Pt2 = FT->Para; Pt2 != NULL; Pt1=Pt1->next,Pt2=Pt2->next)
      if (Pt2->VList.List->Idx != Pt1->VList.List->Idx) break;

    if (Pt2 == NULL) return FT->Finish;
  }

  return FALSE;
}

Bool ModifyStateByEffect(PENode *Effect)
{
  StateOfPlan *FT;
  TokenList   *Pt1, *Pt2;
  PredFact    *Ft1, *Ft2, *Ft3;

  FT = State + Effect->Pred->VList.ParaIdx;

  if (Effect->Type == ATOM) {
     Ft1 = (PredFact *) calloc(1, sizeof(PredFact));
     Ft1->Para = Effect->Pred->next;
     for (Pt1 = Ft1->Para; Pt1 != NULL; Pt1 = Pt1->next)
       Pt1->VList.ParaIdx = NOFOUND;

     Ft3 = NULL;
     for (Ft2 = FT->List; Ft2 != NULL; Ft2 = Ft2->next) Ft3 = Ft2;

     if (Ft3 == NULL) FT->List = Ft1;
     else Ft3->next = Ft1;

     FT->Left++;  FT->Total++;

     free(Effect->Pred);  free(Effect);
     return TRUE;
  }

  Ft2 = NULL;
  for (Ft1 = FT->List; Ft1 != NULL; Ft2=Ft1,Ft1=Ft1->next) {
    Pt1 = Effect->Pred->next;
    for (Pt2 = Ft1->Para; Pt2 != NULL; Pt1=Pt1->next,Pt2=Pt2->next)
      if (Pt2->VList.List->Idx != Pt1->VList.List->Idx) break;

    if (Pt2 == NULL) break;
  }

  if (Ft1 != NULL) {
      if (Ft2 == NULL) FT->List = Ft1->next;
      else Ft2->next = Ft1->next;

      FreeTokenList(Ft1->Para); free(Ft1);
      FT->Total--;
      if (!Effect->Delete) FT->Left--;
  }
  else {
         fprintf(Output, "\nThe following fact don't exist when act deletes it.\n");
         PrintTokenList(TRUE, Effect->Pred);
         fprintf(Output, "\n");
  }

  FreeTokenList(Effect->Pred->next);
  free(Effect->Pred);  free(Effect);

  return TRUE;
}

Bool CheckTypeOfCommonEffect(PredKnowledge *Pd, PENode *PE)
{
  PredKnowledge *PC;
  ActKnowledge  *ActK;
  TypedList     *Pt1;
  TokenList     *Pt2;
  int           PNo;

  PNo = PE->Pred->VList.ParaIdx;
  for (PC = Pd->CPC; PC != NULL; PC = PC->next) {
    if (PE->Type == PC->Type || PNo != PC->PredNo) continue;

    Pt1 = PC->Para;
    for (Pt2 = PE->Pred->next; Pt2 != NULL; Pt1++,Pt2=Pt2->next)
      if (!EqualTwoVLists(&(Pt1->VList), &(Pt2->VList))) break;

    if (Pt2 == NULL && PC->Fact) return TRUE;
  }

  for (ActK = Pd->Act; ActK != NULL; ActK = ActK->next)
    for (PC = ActK->PC; PC != NULL; PC = PC->next) {
      if (PE->Type == PC->Type || PNo != PC->PredNo) continue;

      Pt1 = PC->Para;
      for (Pt2 = PE->Pred->next; Pt2 != NULL; Pt1++,Pt2=Pt2->next)
        if (!ValueListInValueList(&(Pt1->VList), &(Pt2->VList))) break;

      if (Pt2 == NULL && PC->Fact) return TRUE;
    }

  return FALSE;
}

void SetDeleteFlagToNCEffect(PENode *PE)
{
  NCAction *nAct;
  PENode   *PE1;

  for (nAct = TNCA; nAct != NULL; nAct = nAct->prev) {
    for (PE1 = nAct->Pred->CEffect; PE1 != NULL; PE1 = PE1->next)
      if (!PE1->Delete && PE1->Type != PE->Type &&
         EqualTwoTokenLists(PE1->Pred, PE->Pred)) break;

      if (PE1 != NULL) { PE1->Delete = TRUE; break; }
  }
}

Bool HandleUnconfirmEffect(PredKnowledge *Pd, PENode *PE)
{
  PredKnowledge *PC;
  ActKnowledge  *ActK;
  TokenList     *Pt1, *Pt2;
  int           idx;

  idx = PE->Pred->VList.ParaIdx;

  State[idx].Left--;
  if (State[idx].Left > 0) return FALSE;

//PrintPredication(20, Pd); fprintf(Output, "\n");
  ActK = Pd->Act;
  Pt2 = State[idx].List->Para;
  for (Pt1 = PE->Pred->next; Pt1 != NULL; Pt1=Pt1->next,Pt2=Pt2->next) {
    if (Pt1->VList.NumValue == 1) continue;

    CopyValueList(&(Pt1->VList), &(Pt2->VList));
    idx = Pt1->VList.ParaIdx;
    CopyValueList(&((ActK->Para+idx)->VList), &(Pt2->VList));
  }

  InstanceEffectOfAction(ActK);
  for (PC = ActK->PC; PC != NULL; PC = PC->next)
    ChangeOnePCByAction(PC, ActK->Para);

  return TRUE;
}

void GetCommonPCListForPred(PredKnowledge *Pd)
{
  PredKnowledge *PC1, *PC2, *PC3, *PC4, *PC5;
  ActKnowledge  *ActK, *ActK1;
  TypedList     *Pt1;
  TokenList     *Pt2;
  PENode        *PE;
  int           i, j, idx, Num, *PCIdx;

  PCIdx = (int *) calloc(Pd->NumAct, sizeof(int));

  ActK = Pd->Act;
  PC3 = NULL;
  for (PC1 = ActK->PC; PC1 != NULL; PC1 = PC4) {
    PC4 = PC1->next;

    for (i=1,ActK1=ActK->next; ActK1 != NULL; i++,ActK1=ActK1->next) {
      for (j=0,PC2=ActK1->PC; PC2 != NULL; j++,PC2=PC2->next)
        if (PC2->Type==PC1->Type && EqualTwoPredications(PC1, PC2)) {
           PCIdx[i] = j;
           break;
        }

      if (PC2 == NULL) break;
    }

    if (ActK1 != NULL) { PC3 = PC1;  continue; }

    // check the parameters of PC1
    Num = NumParaOfPred(PC1->PredNo);
    Pt1 = PC1->Para;
    for (j = 0; j < Num; j++,Pt1++) {
      idx = Pt1->VList.ParaIdx;
      if (!IsConstant(idx)) {
         idx = (ActK->Para+idx)->VList.ParaIdx;
         if (IsExtraPara(idx)) break;
      }
    }

    if (j < Num) { PC3 = PC1;  continue; }

    // delete all pc from other actions
    for (i=1,ActK1=ActK->next; ActK1 != NULL; i++,ActK1=ActK1->next) {
      PC2 = NULL;
      PC5 = ActK1->PC;
      for (j = 0; j < PCIdx[i]; j++) PC2=PC5,PC5=PC5->next;

      if (PC2 == NULL) ActK1->PC = PC5->next;
      else PC2->next = PC5->next;

      FreePredKnowledge(PC5);  free(PC5);
    }

    // append the common pc
    if (PC3 == NULL) ActK->PC = PC4;
    else PC3->next = PC4;

    Pt1 = PC1->Para;
    for (j = 0; j < Num; j++,Pt1++) {
      idx = Pt1->VList.ParaIdx;
      if (!IsConstant(idx))
         Pt1->VList.ParaIdx = (ActK->Para+idx)->VList.ParaIdx;
    }

    PC1->next = Pd->CPC;
    Pd->CPC = PC1;
//PrintPredication(20, Pd); fprintf(Output, "\n");
  }

  free(PCIdx);

  // Delete all common PCs which are not deleted
  // by common effects of the Pd
  PC2 = NULL;
  for (PC1 = Pd->CPC; PC1 != NULL; PC1 = PC3) {
    PC3 = PC1->next;

    Num = NumParaOfPred(PC1->PredNo);
    for (PE = Pd->CEffect; PE != NULL; PE = PE->next)
      if (PE->Type!=PC1->Type && PE->Pred->VList.ParaIdx==PC1->PredNo) {
         Pt1 = PC1->Para;
         for (Pt2 = PE->Pred->next; Pt2 != NULL; Pt1++,Pt2=Pt2->next)
           if (!EqualTwoVLists(&(Pt1->VList), &(Pt2->VList))) break;

         if (Pt2 == NULL) break;
      }

    if (PE != NULL) PC2 = PC1;
    else {
           if (PC2 == NULL) Pd->CPC = PC3;
           else PC2->next = PC3;

           FreePredKnowledge(PC1);  free(PC1);
    }
  }
}

void GetCommonInfoOfPred(PredKnowledge *Pd)
{
  ActKnowledge *ActK, *ActK1;
  TokenList    *Pt;
  PENode       *PE1, *PE2, *PE3, *PE4, *PE5;
  int          i, j, *EffIdx;

  EffIdx = (int *) calloc(Pd->NumAct, sizeof(int));

//PrintPredication(20, Pd); fprintf(Output, "\n");
  ActK = Pd->Act;
  PE3 = NULL;   PE1 = ActK->Effect;
  while (PE1 != NULL) {
    PE4 = PE1->next;

    for (i=1,ActK1=ActK->next; ActK1 != NULL; i++,ActK1=ActK1->next) {
      for (j=0,PE2=ActK1->Effect; PE2 != NULL; j++,PE2=PE2->next)
        if (PE2->Type==PE1->Type && EqualTwoTokenLists(PE1->Pred, PE2->Pred)) {
           EffIdx[i] = j;
           break;
        }

      if (PE2 == NULL) break;
    }

    if (ActK1 != NULL) { PE3 = PE1; PE1 = PE4; continue; }

    for (Pt = PE1->Pred->next; Pt != NULL; Pt = Pt->next)
      if (Pt->VList.NumValue != 1) break;

    for (i=1,ActK1=ActK->next; ActK1 != NULL; i++,ActK1=ActK1->next) {
      PE2 = NULL;
      PE5 = ActK1->Effect;
      for (j = 0; j < EffIdx[i]; j++) PE2=PE5,PE5=PE5->next;

      if (Pt != NULL) {
         if (PE5->Type == NOT) PE5->Delete = TRUE;
      }
      else {
             if (PE2 == NULL) ActK1->Effect = PE5->next;
             else PE2->next = PE5->next;

             FreeTokenList(PE5->Pred);  free(PE5);
      }
    }

    if (Pt == NULL) {
       if (PE3 == NULL) ActK->Effect = PE4;
       else PE3->next = PE4;

       PE1->next = Pd->CEffect;
       Pd->CEffect = PE1;
       PE1 = PE4;
       continue;
    }

    if (PE1->Type == ATOM) {
       PE3 = PE1;  PE1 = PE4;
       continue;
    }

    PE1->Delete = TRUE;
    if (!CheckTypeOfCommonEffect(Pd, PE1)) {
       SetDeleteFlagToNCEffect(PE1);
       PE3 = PE1;  PE1 = PE4;
    }
    else if (HandleUnconfirmEffect(Pd, PE1)) {
            PE3 = NULL;
            PE1 = ActK->Effect;
         }
         else { PE3 = PE1;  PE1 = PE4; }
  }

  free(EffIdx);

  GetCommonPCListForPred(Pd);
}

void DeleteAllNCActionByNoFactPC(NCAction *nAct)
{
  PredKnowledge *PC;
  ActKnowledge  *ActK, *ActK1;

  for ( ; nAct != NULL; nAct = nAct->next)
    for (ActK = nAct->Pred->Act; ActK != NULL; ActK = ActK1) {
      ActK1 = ActK->next;
      for (PC = ActK->PC; PC != NULL; PC = PC->next)
        if (!PC->Fact && !FindOneNoConfirmFact(PC, nAct)) {
           DeleteActKnowledge(ActK);
           nAct->Change = TRUE;
           break;
        }
    }
}

PENode* PredInEffectOfAction(PredKnowledge *Pred, PENode *PE)
{
  TypedList *Pt1;
  TokenList *Pt2;

  for (; PE != NULL; PE = PE->next) {
    Pt1 = Pred->Para;
    Pt2 = PE->Pred;

    if (Pred->Type!=PE->Type || Pred->PredNo!=Pt2->VList.ParaIdx) continue;

    for (Pt2 = Pt2->next; Pt2 != NULL; Pt1++,Pt2=Pt2->next)
      if (!ValueListInValueList(&(Pt1->VList), &(Pt2->VList))) break;

    if (Pt2 == NULL) break;
  }

  return PE;
}

Bool NOTPredInOneEffect(PredKnowledge *Pred, PENode *Effect)
{
  TypedList *Pt1;
  TokenList *Pt2;
  Bool      IN;

  Pt1 = Pred->Para;
  Pt2 = Effect->Pred;
  IN = (Pred->Type!=Effect->Type && Pred->PredNo==Pt2->VList.ParaIdx);
  for (Pt2=Pt2->next; IN && Pt2!=NULL; Pt1++,Pt2=Pt2->next)
    if (Pt1->VList.NumValue < Pt2->VList.NumValue)
       IN = ValueListInValueList(&(Pt1->VList), &(Pt2->VList));
    else
       IN = ValueListInValueList(&(Pt2->VList), &(Pt1->VList));

  return IN;
}

Bool DeleteNotPCFromEffect(PredKnowledge *PC, PENode *Effect)
{
  TypedList *Pt1;
  TokenList *Pt2;
  VList     *Pt;
  int       Count;

  Count = NumParaOfPred(PC->PredNo);
  Pt1 = PC->Para;
  Pt2 = Effect->Pred;
  for (Pt2 = Pt2->next; Pt2 != NULL; Pt1++,Pt2=Pt2->next) {
    if (Pt2->VList.NumValue == 1) { Count--; continue; }

    for (Pt = Pt1->VList.List; Pt != NULL; Pt = Pt->next)
      DeleteOneValueFromValueList(Pt->Idx, &(Pt2->VList));

    if (Pt2->VList.NumValue == 0) {
       Count = 0;
       break;
    }
  }

  return (Count != 0);
}

void ChangeNCActionByCEffect(PredKnowledge *Pd, PredKnowledge *PC, PENode *Effect)
{
  PredKnowledge *PC1;
  ActKnowledge  *ActK, *ActK1;
  TypedList     *P1, *P2;
  TokenList     *Pt;
  PENode        *PE;
  Bool          Change;
  int           i, j, Num;

  DeleteNotPCFromEffect(PC, Effect);

  for (Pt = Effect->Pred->next; Pt != NULL; Pt = Pt->next)
    if (!IsConstant(Pt->VList.ParaIdx)) {
       P1 = Pd->Para + Pt->VList.ParaIdx;
       CopyValueList(&(P1->VList), &(Pt->VList));
    }

  for (PE = Pd->CEffect; PE != NULL; PE = PE->next)
    for (Pt = PE->Pred->next; Pt != NULL; Pt = Pt->next) {
      i = Pt->VList.ParaIdx;
      P1 = Pd->Para + i;
      if (!IsConstant(i) && Pt->VList.NumValue != P1->VList.NumValue)
         CopyValueList(&(Pt->VList), &(P1->VList));
    }

//PrintPredication(20, PC); fprintf(Output, "\n");
//PrintPredication(20, Pd); fprintf(Output, "\n");
  for (ActK = Pd->Act; ActK != NULL; ActK = ActK1) {
    ActK1 = ActK->next;

    Change = FALSE;
    Num = NumParaOfAct(ActK->ActNo);
    P1 = ActK->Para;
    for (i = 0; i < Num; P1++,i++) {
      j = P1->VList.ParaIdx;
      if (IsConstant(j) || IsExtraPara(j)) continue;

      P2 = Pd->Para + j;
      if (EqualTwoVLists(&(P1->VList), &(P2->VList))) continue;

      if (ValueListInValueList(&(P2->VList), &(P1->VList))) {
         CopyValueList(&(P1->VList), &(P2->VList));
         Change = TRUE;
      }
      else if (ValueListInValueList(&(P1->VList), &(P2->VList))) {
              DeleteActKnowledge(ActK);
              Change = FALSE;
              break;
           }
    }

    if (Change) {
       for (PC1 = ActK->PC; PC1 != NULL; PC1 = PC1->next)
           ChangeOnePCByAction(PC1, ActK->Para);

       InstanceEffectOfAction(ActK);
    }
  }
}

void DeleteNotPCFromEffectOfNCAction(NCAction *Tail, PredKnowledge *PC)
{
  PredKnowledge *PC1, *Pd;
  ActKnowledge  *ActK, *ActK1;
  NCAction      *nAct;
  TypedList     *Pt1;
  TokenList     *Pt2;
  PENode        *Effect;

  for (nAct = Tail; nAct != NULL; nAct = nAct->prev) {
    Pd = nAct->Pred;

//PrintPredication(20, Pd); fprintf(Output, "\n");
//PrintPredication(20, PC); fprintf(Output, "\n");
    for (Effect = Pd->CEffect; Effect != NULL; Effect = Effect->next)
      if (NOTPredInOneEffect(PC, Effect)) break;

    if (Effect != NULL) {
       nAct->Change = TRUE;
       ChangeNCActionByCEffect(Pd, PC, Effect);
       continue;
    }

    for (ActK = Pd->Act; ActK != NULL; ActK = ActK1) {
      ActK1 = ActK->next;

      for (Effect = ActK->Effect; Effect != NULL; Effect = Effect->next)
        if (NOTPredInOneEffect(PC, Effect)) break;

      if (Effect == NULL) continue;

//PrintPredication(20, Pd); fprintf(Output, "\n");
      nAct->Change = TRUE;
      if (!DeleteNotPCFromEffect(PC, Effect)) {
         DeleteActKnowledge(ActK);
         DeleteAllNCActionByNoFactPC(nAct->next);
      }
      else {
             for (Pt2 = Effect->Pred->next; Pt2 != NULL; Pt2=Pt2->next)
               if (!IsConstant(Pt2->VList.ParaIdx)) {
                  Pt1 = ActK->Para + Pt2->VList.ParaIdx;
                  CopyValueList(&(Pt1->VList), &(Pt2->VList));
               }

             for (PC1 = ActK->PC; PC1 != NULL; PC1 = PC1->next)
               ChangeOnePCByAction(PC1, ActK->Para);

             InstanceEffectOfAction(ActK);
      }
    }
  }
}

Bool FindAndInstanceOnePC(PredKnowledge *Pd)
{
  TypedList *Pt1;
  TokenList *Pt2;
  PredFact  *Ft;

  for (Ft = State[Pd->PredNo].List; Ft != NULL; Ft = Ft->next) {
    Pt1 = Pd->Para;
    for (Pt2 = Ft->Para; Pt2 != NULL; Pt1++,Pt2=Pt2->next)
      if (!CheckValueList(Pt2->VList.List->Idx, &(Pt1->VList))) break;

    if (Pt2 == NULL) {
       Pt1 = Pd->Para;
       for (Pt2 = Ft->Para; Pt2 != NULL; Pt1++,Pt2=Pt2->next)
         if (Pt1->VList.NumValue > 1) CopyValueList(&(Pt1->VList), &(Pt2->VList));

       return TRUE;
    }
  }

  return FALSE;
}

Bool InstancePC(PredKnowledge *PC)
{
  TypedList *Pt;
  int       i, Num;

  Num = NumParaOfPred(PC->PredNo);
  Pt = PC->Para;
  for (i = 0; i < Num; i++,Pt++)
    if (Pt->VList.NumValue != 1) break;

  return (i >= Num);
}

Bool ChangeNCAListByCPCOfActions(NCAction *Tail, PredKnowledge *Pd)
{
  PredKnowledge *PC, *PC1, *PC2, *PC3, *PC4, *PC5;
  ActKnowledge  *ActK, *ActK1;
  TypedList     *Pt, *Pt1;
  Bool          Change1, Change2, Instance;
  int           i, j, Num, *CPCIdx;

  CPCIdx = (int *) calloc(Pd->NumAct, sizeof(int));

  ActK = Pd->Act;
  Change1 = FALSE;  PC3 = NULL;
  for (PC = ActK->PC; PC != NULL; PC = PC2) {
    for (i=1,ActK1=ActK->next; ActK1 != NULL; i++,ActK1=ActK1->next) {
      for (j=0,PC1=ActK1->PC; PC1 != NULL; j++,PC1=PC1->next)
        if (EqualTwoPredications(PC, PC1)) { CPCIdx[i] = j; break; }

      if (PC1 == NULL) break;
    }

    PC2 = PC->next;
    if (ActK1 != NULL) { PC3 = PC;  continue; }

    Change2 = FALSE;
    if (PC->Fact) {
       Instance = InstancePC(PC);
       if (Instance) DeleteNotPCFromEffectOfNCAction(Tail, PC);
    }
    else {
           Change2 = ExecNFActionForOneNFPC(Tail, PC);
           Instance = InstancePC(PC);
    }

    Change1 = Change1 || Change2;

    Num = NumParaOfPred(PC->PredNo);

    if (Change2) {
       for (i=1,ActK1=ActK->next; ActK1 != NULL; i++,ActK1=ActK1->next) {
         PC1 = ActK1->PC;
         for (j = 0; j < CPCIdx[i]; j++) PC1 = PC1->next;

         Pt = PC->Para;  Pt1 = PC1->Para;
         for (j = 0; j < Num; j++,Pt++,Pt1++)
           CopyValueList(&(Pt1->VList), &(Pt->VList));

         ChangeParaOfActionByPC(ActK1, PC1);
         for (PC5 = ActK1->PC; PC5 != NULL; PC5 = PC5->next)
           ChangeOnePCByAction(PC5, ActK1->Para);
       }

       ChangeParaOfActionByPC(ActK, PC);
       for (PC1 = ActK->PC; PC1 != NULL; PC1 = PC1->next)
         ChangeOnePCByAction(PC1, ActK->Para);

       ModifyParaOfPredByActions(Pd);
    }

    if (Instance) {
       for (i=1,ActK1=ActK->next; ActK1 != NULL; i++,ActK1=ActK1->next) {
         PC4 = NULL;
         PC1 = ActK1->PC;
         for (j = 0; j < CPCIdx[i]; j++) PC4=PC1,PC1=PC1->next;

         if (PC4 == NULL) ActK1->PC = PC1->next;
         else PC4->next = PC1->next;

         FreeTypedArray(Num, PC1->Para);  free(PC1);
       }

       if (PC3 == NULL) ActK->PC = PC2;
       else PC3->next = PC2;

       FreeTypedArray(Num, PC->Para);  free(PC);
    }
  }

  free(CPCIdx);
  return Change1;
}

#ifdef WHEN_CLAUSE
Bool FindConditionOfWhenClause(PENode *PE)
{
  TokenList *Pt1, *Pt2;
  PredFact  *Fact;
  int       PNo;

  PNo = PE->Pred->VList.ParaIdx;
  if (State[PNo].Left == 0) return FALSE;

  for (Fact = State[PNo].List; Fact != NULL; Fact = Fact->next) {
    Pt1 = PE->Pred->next;
    for (Pt2 = Fact->Para; Pt2 != NULL; Pt1=Pt1->next,Pt2=Pt2->next)
      if (Pt1->VList.List->Idx != Pt2->VList.List->Idx) break;

    if (Pt2 == NULL) return TRUE;
  }

  return FALSE;
}

void GetCommonWhenForPred(PredKnowledge *Pd)
{
  PENode *PE, *PE1, *PE2;

  Pd->CondEffect = NULL;
  for (PE = Pd->Act->CondEffect; PE != NULL; PE = PE->next) {
    PE1 = CopyWhenClause(PE);
    if (Pd->CondEffect == NULL) Pd->CondEffect = PE1;
    else PE2->next = PE1;
    PE2 = PE1;
  }
}
#endif

Bool HandleOneEffect(NCAction *Tail, PredKnowledge *Pd, PENode *PE)
{
  PredKnowledge *PC, *PC1;
  TypedList     *Pt1;
  TokenList     *Pt2;
  int           PNo;

  PC1 = NULL;
  PNo = PE->Pred->VList.ParaIdx;
  for (PC = Pd->CPC; PC != NULL; PC1=PC,PC=PC->next) {
    if (PE->Type == PC->Type || PNo != PC->PredNo) continue;

    Pt1 = PC->Para;
    for (Pt2 = PE->Pred->next; Pt2 != NULL; Pt1++,Pt2=Pt2->next)
      if (Pt1->VList.List->Idx != Pt2->VList.List->Idx) break;

    if (Pt2 == NULL) break;
  }

  if (PC != NULL) {
     if (PC->Fact) DeleteNotPCFromEffectOfNCAction(Tail, PC);
     else ExecNFActionForOneNFPC(Tail, PC);

     if (PC1 == NULL) Pd->CPC = PC->next;
     else PC1->next = PC->next;

     FreePredKnowledge(PC);  free(PC);
  }

  return ModifyStateByEffect(PE);
}

Bool HandleUnconfirmCommonEffect(NCAction **Tail, PredKnowledge *Pd, PENode *PE)
{
  PredKnowledge *PC;
  ActKnowledge  *ActK, *ActK1;
  TokenList     *Pt1, *Pt2;
  TypedList     *Pt3, *Pt4;
  PENode        *PE1;
  Status        Ok;
  Bool          Delete;
  int           i, j, idx, Num;

  idx = PE->Pred->VList.ParaIdx;

  State[idx].Left--;
  PE->Delete = TRUE;
  if (State[idx].Left > 0) return FALSE;

  ModifyStateByNFActions(Tail, TRUE);

  Pt2 = State[idx].List->Para;
  for (Pt1 = PE->Pred->next; Pt1 != NULL; Pt1=Pt1->next,Pt2=Pt2->next) {
    if (Pt1->VList.NumValue == 1) continue;

    CopyValueList(&(Pt1->VList), &(Pt2->VList));
    idx = Pt1->VList.ParaIdx;
    CopyValueList(&((Pd->Para+idx)->VList), &(Pt2->VList));
  }

  // Instance all Common PCs Of Pred
  for (PC = Pd->CPC; PC != NULL; PC = PC->next) {
    Num = NumParaOfPred(PC->PredNo);
    Pt3 = PC->Para;
    for (i = 0; i < Num; i++,Pt3++) {
      j = Pt3->VList.ParaIdx;
      Pt4 = Pd->Para + j;
      if (!IsConstant(j) && Pt3->VList.NumValue != Pt4->VList.NumValue)
         CopyValueList(&(Pt3->VList), &(Pt4->VList));
    }
  }

  // Instance all common effects Of Pred
  Num = NumParaOfPred(Pd->PredNo) + Pd->NumEP;
  for (PE1 = Pd->CEffect; PE1 != NULL; PE1 = PE1->next)
    InstanceTokenListByTypedList(PE1->Pred, Num, Pd->Para);

  for (ActK = Pd->Act; ActK != NULL; ActK = ActK1) {
    ActK1 = ActK->next;

    Ok = ChangeParaOfActionByPred(ActK, Pd);

    if (Ok == ERROR) {
       DeleteActKnowledge(ActK);
       continue;
    }

    Delete = FALSE;
    for (PC = ActK->PC; !Delete && PC != NULL; PC = PC->next) {
      ChangeOnePCByAction(PC, ActK->Para);
      if (!PC->Fact && !FindOneNoConfirmFact(PC, NCA)) {
         if (FindAndInstantByFacts(PC) == 0) Delete = TRUE;
         else PC->Fact = TRUE;
      }
    }

    if (Delete) DeleteActKnowledge(ActK);
    else InstanceEffectOfAction(ActK);
  }
//PrintPredication(20, Pd); fprintf(Output, "\n");

  return TRUE;
}

Bool ModifyStateByCEffect(NCAction *Tail, PredKnowledge *Pd)
{
  TokenList *Pt;
  PENode    *PE1, *PE2, *PE3;
  Bool      CState;
#ifdef WHEN_CLAUSE
  Bool      Ok;
#endif

//PrintPredication(20, Pd); fprintf(Output, "\n");
  GetCommonInfoOfPred(Pd);
//PrintPredication(20, Pd); fprintf(Output, "\n");

  PE1 = NULL;
  PE3 = Pd->CEffect;  CState = FALSE;
  while (PE3 != NULL) {
//PrintPlanList(); PrintPredication(20, Pd); fprintf(Output, "\n");
    PE2 = PE3->next;

    for (Pt = PE3->Pred->next; Pt != NULL; Pt = Pt->next)
      if (Pt->VList.NumValue > 1) break;

    if (Pt == NULL) {
       CState = HandleOneEffect(Tail, Pd, PE3) || CState;
       if (PE1 == NULL) Pd->CEffect = PE2;
       else PE1->next = PE2;
       PE3 = PE2;
    }
    else if (PE3->Type == NOT && !PE3->Delete &&
            CheckTypeOfCommonEffect(Pd, PE3) &&
            HandleUnconfirmCommonEffect(&Tail, Pd, PE3)) {
            GetCommonInfoOfPred(Pd);
            PE1 = NULL;  PE3 = Pd->CEffect;
         }
    else { PE1 = PE3;  PE3 = PE2; }
  }
//PrintPlanList(); PrintPredication(20, Pd); fprintf(Output, "\n");

#ifdef WHEN_CLAUSE
  GetCommonWhenForPred(Pd);
  CState = CState || (Pd->CondEffect != NULL);
  for (PE2 = Pd->CondEffect; PE2 != NULL; PE2 = PE1) {
    Ok = FindConditionOfWhenClause(PE2->sons);

    for (PE1 = PE2->Effect; PE1 != NULL; PE1 = PE3) {
      PE3 = PE1->next;
      if (Ok) ModifyStateByEffect(PE1);
      else { FreeTokenList(PE1->Pred); free(PE1); }
    }

    PE1 = PE2->next;
    FreeTokenList(PE2->sons->Pred); free(PE2->sons);
    free(PE2);
  }
  Pd->CondEffect = NULL;
#endif

  return CState;
}

Bool FindOneCurrentFact1(PredKnowledge *Pred, Bool *Change)
{
  TypedList *Pt1;
  TokenList *Pt2, *Pt3, *Fact;
  PredFact  *FT;
  int       PNo;

  PNo = Pred->PredNo;

  Fact = NULL;
  for (FT = State[PNo].List; FT != NULL; FT = FT->next) {
    Pt1 = Pred->Para;

    for (Pt2 = FT->Para; Pt2 != NULL; Pt1++,Pt2=Pt2->next)
      if (!CheckValueList(Pt2->VList.List->Idx, &(Pt1->VList))) break;

    if (Pt2 != NULL) continue;

    if (Fact == NULL) {
       Fact = CopyTokenList(FT->Para);
       if (State[PNo].Left == 0) break;
    }
    else {
           Pt3 = Fact;
           for (Pt2 = FT->Para; Pt2 != NULL; Pt2=Pt2->next,Pt3=Pt3->next)
             InsertOneValueIntoValueList(Pt2->VList.List->Idx, &(Pt3->VList));
    }
  }

  if (Fact == NULL) return FALSE;

  *Change = CopyTokenListIntoTypeList(Pred->Para, Fact);
  FreeTokenList(Fact);

  return TRUE;
}

Status ChangeParaOfNFPC(NCAction *NFCA, PredKnowledge *PC);
Bool HandleCommonPCList(NCAction *Tail, PredKnowledge *Pred)
{
  PredKnowledge *PC, *PC1;
  ActKnowledge  *ActK;
  PENode        *PE;
  Bool          Ok, Change, Change1;
  int           Num1, Num2;

  Num1 = NumParaOfPred(Pred->PredNo) + Pred->NumEP;

  Change = FALSE;
  for (PC = Pred->CPC; PC != NULL; PC = PC->next)
    if (!InstancePC(PC)) {
       if (PC->Fact) {
          FindOneCurrentFact1(PC, &Change1);
          Change = Change || Change1;
       }
       else {
              Ok = ChangeParaOfNFPC(Tail, PC);
              if (Ok != ERROR) Change = Change || Ok;
       }

       Num2 = NumParaOfPred(PC->PredNo);
       ChangePara1ByPara2(Num1, Pred->Para, Num2, PC->Para);
    }

  if (Change) {
     // Instance all common effects Of Pred
     for (PE = Pred->CEffect; PE != NULL; PE = PE->next)
       InstanceTokenListByTypedList(PE->Pred, Num1, Pred->Para);

     for (ActK = Pred->Act; ActK != NULL; ActK = ActK->next) {
       ChangeParaOfActionByPred(ActK, Pred);

       for (PC1 = ActK->PC; PC1 != NULL; PC1 = PC1->next)
         ChangeOnePCByAction(PC1, ActK->Para);
       InstanceEffectOfAction(ActK);
     }
  }

  return Change;
}

Bool ModifyStateByNFActions(NCAction **TAIL, Bool CState)
{
  PredKnowledge *PC, *PC1, *Pred;
  ActKnowledge  *ActK, *ActK1;
  NCAction      *nAct, *nAct1, *nAct2, *nAct3, *Tail;
  Bool          Ok, Change, Change1, CState1, CState2, Delete;

  CState2 = FALSE;
  do {
       CState1 = FALSE;

       Tail = *TAIL;
       if (Tail != NULL) Tail = Tail->next;

       for (nAct = NCA; nAct != Tail; nAct = nAct1) {
//PrintPlanList();
         nAct1 = nAct->next;

         Change = nAct->Change;
         if (!(CState || CState1 || Change)) continue;

         Pred = nAct->Pred;
//PrintPredication(12, Pred); fprintf(Output, "\n");
         Change = HandleCommonPCList(nAct->prev, Pred);
//PrintPredication(12, Pred); fprintf(Output, "\n");

         for (ActK = Pred->Act; ActK != NULL; ActK = ActK1) {
           ActK1 = ActK->next;

           Delete = FALSE;
           for (PC = ActK->PC; !Delete && PC != NULL; PC = PC->next) {
             if (!InstancePC(PC)) {
                if (!PC->Fact) {
                   Ok = ChangeParaOfNFAction(nAct->prev, ActK);
                   if (Ok == ERROR) Delete = TRUE;
                   else Change = Change || Ok;
                }
                else {
                       Delete = !FindOneCurrentFact1(PC, &Change1);
                       if (PC->Type == NOT) Delete = !Delete;
                       if (!Delete && Change1) {
                          ChangeParaOfActionByPC(ActK, PC);
                          for (PC1 = ActK->PC; PC1 != NULL; PC1 = PC1->next)
                            ChangeOnePCByAction(PC1, ActK->Para);
                          InstanceEffectOfAction(ActK);
                          Change = TRUE;
                        }
                }
                continue;
             }

             Ok = CheckTheFactWithLeftFact(PC);
             Delete = !Ok;
             if (Ok) PC->Fact = Change = TRUE;
             else Delete = !FindOneNoConfirmFact(PC, nAct);
           }

           if (Delete) { DeleteActKnowledge(ActK);  Change = TRUE; }
         }

         if (!Change) continue;

//PrintPredication(12, Pred); fprintf(Output, "\n");
         ModifyParaOfPredByActions(Pred);
         CState1 = ModifyStateByCEffect(nAct->prev, Pred);
         nAct->Change = FALSE;
         if (Pred->NumAct > 1) {
            CState1 = ChangeNCAListByCPCOfActions(nAct->prev, Pred) || CState1;
            CState1 = ModifyStateByCEffect(nAct->prev, Pred) || CState1;
         }
         else {
                ActK = Pred->Act;
                for (PC = ActK->PC; PC != NULL; PC = PC->next)
                  CState1 = (!PC->Fact && ExecNFActionForOneNFPC(nAct->prev,PC)) || CState1;

                if (Pred->CEffect==NULL && ActK->Effect==NULL) {
                   nAct2 = nAct->prev;
                   nAct3 = nAct->next;

                   if (nAct == *TAIL) *TAIL = nAct2;

                   free(nAct);

                   if (nAct2 == NULL) NCA = nAct3;
                   else nAct2->next = nAct3;

                   if (nAct3 == NULL) TNCA = nAct2;
                   else nAct3->prev = nAct2;
                }
         }
       }

       CState = CState1;
       CState2 = CState2 || CState1;
  } while (CState);

  return CState2;
}

Bool ChangePCWithCommonEffect(PredKnowledge *PC, PredKnowledge *Pred, PENode *PE)
{
  ActKnowledge *ActK, *ActK1, *ActK2;
  TypedList    *Pt, *Pt1;
  TokenList    *Pt2;
  Bool         Changed;
  int          i, idx, Num1, Num2;

  Pt1 = PC->Para;
  Pt2 = PE->Pred;
  Changed = FALSE;
  for (Pt2 = Pt2->next; Pt2 != NULL; Pt1++,Pt2=Pt2->next)
    if (Pt1->VList.NumValue != Pt2->VList.NumValue) {
       CopyValueList(&(Pt2->VList), &(Pt1->VList));
       Pt = Pred->Para + Pt2->VList.ParaIdx;
       CopyValueList(&(Pt->VList), &(Pt1->VList));
       Changed = TRUE;
    }

  for (PE = Pred->CEffect; PE != NULL; PE = PE->next)
    for (Pt2 = PE->Pred->next; Pt2 != NULL; Pt2 = Pt2->next) {
      Pt = Pred->Para + Pt2->VList.ParaIdx;
      if (Pt2->VList.NumValue != Pt->VList.NumValue) {
         CopyValueList(&(Pt2->VList), &(Pt->VList));
         Changed = TRUE;
      }
    }

  Num1 = NumParaOfPred(Pred->PredNo) + Pred->NumEP;
  ActK2 = NULL;  ActK = Pred->Act;
  while (ActK != NULL) {
    Num2 = NumParaOfAct(ActK->ActNo);
    Pt1 = ActK->Para;
    for (i = 0; i < Num2; i++,Pt1++) {
      idx = Pt1->VList.ParaIdx;
      if (idx > Num1) continue;
      Pt = Pred->Para + idx;
      if (!ValueListInValueList(&(Pt1->VList), &(Pt->VList))) break;
    }

    ActK1 = ActK->next;
    if (i >= Num2) ActK2 = ActK;
    else {
           DeleteActKnowledge(ActK);
           Changed = TRUE;
    }
    ActK = ActK1;
  }

  return Changed;
}

Bool ExecNFActionForOneNFPC(NCAction *Tail, PredKnowledge *PC)
{
  ActKnowledge *ActK, *ActK1;
  NCAction     *nAct, *nAct1;
  PENode       *PE;
  Bool         Change;
  int          Num;

  for (nAct1 = Tail; nAct1 != NULL; nAct1 = nAct1->prev) {
    for (PE = nAct1->Pred->CEffect; PE != NULL; PE = PE->next)
      if (PCMatchsEffect(PC, PE)) break;

    if (PE != NULL) break;
  }

  Change = FALSE;
  if (nAct1 != NULL) Change = ChangePCWithCommonEffect(PC, nAct1->Pred, PE);
  else {
         Num = 0;
         for (nAct = Tail; nAct != NULL; nAct = nAct->prev)
           for (ActK = nAct->Pred->Act; ActK != NULL; ActK = ActK->next)
             if (PredInEffectOfAction(PC, ActK->Effect) != NULL) {
                if (Num == 1) return FALSE;

                Num++;  nAct1 = nAct;
                break;
             }

         if (nAct1 != NULL)
            for (ActK = nAct1->Pred->Act; ActK != NULL; ActK = ActK1) {
              ActK1 = ActK->next;
              if (PredInEffectOfAction(PC, ActK->Effect) == NULL) {
                 DeleteActKnowledge(ActK);
                 Change = TRUE;
              }
            }
  }

  if (nAct1 == NULL) {
     PC->Fact = TRUE;
     FindAndInstanceOnePC(PC);
  }
  else if (Change) {
          nAct1->Change = TRUE;
          ModifyParaOfPredByActions(nAct1->Pred);
          ModifyStateByCEffect(nAct1->prev, nAct1->Pred);
       }

  return Change;
}
